package ink.carnation.imtalk.aspect;

import ink.carnation.imtalk.annotation.IPLimit;
import ink.carnation.imtalk.model.IMResult;
import ink.carnation.imtalk.util.IPUtils;
import ink.carnation.imtalk.util.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * Created with IDEA
 * author:桂乙侨
 * Date:2020/9/29
 * Time:17:19
 */
@Aspect
@Component
@Slf4j
public class IPLimitAspect {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Around("@annotation(limit)")
    private Object ipLimit(final ProceedingJoinPoint joinPoint , IPLimit limit){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        StringBuilder builder = new StringBuilder();
        builder.append(joinPoint.getSignature());
        String ip = IPUtils.getIpAddress(request);
        builder.append(ip);
        //待完善
        Integer count = (Integer) redisTemplate.boundValueOps(RedisKeyUtils.getIPLimitKey(builder.toString())).get();
        log.info(String.valueOf(count));
        if( count == null){
            redisTemplate.boundValueOps(RedisKeyUtils.getIPLimitKey(ip)).set(limit.count(),limit.time(), TimeUnit.SECONDS);
        }else if(count <= 0){
            return IMResult.failure("请求太过频繁，请稍后重试！");
        }else
            redisTemplate.boundValueOps(RedisKeyUtils.getIPLimitKey(ip)).decrement();

        try {
            return  joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return IMResult.failure("服务器异常");
    }

}
